home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / aztecnos.arc / DIRUTIL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-02-13  |  8.3 KB  |  394 lines

  1. /* dirutil.c - MS-DOS directory reading routines
  2.  *
  3.  * Bdale Garbee, N3EUA, Dave Trulli, NN2Z, and Phil Karn, KA9Q
  4.  * Directory sorting by Mike Chepponis, K3MC
  5.  * New version using regs.h by Russell Nelson.
  6.  */
  7.  
  8. #include <stdio.h>
  9. #include "global.h"
  10. #include "regs.h"
  11.  
  12. #define ST_RDONLY    0x01        /* Read only attribute */
  13. #define ST_HIDDEN    0x02        /* Hidden file */
  14. #define ST_SYSTEM    0x04        /* System file */
  15. #define ST_LABEL    0x08        /* Volume label */
  16. #define ST_DIRECT    0x10        /* Directory */
  17. #define ST_ARCH        0x20        /* Archive */
  18.  
  19. FILE *tmpfile();
  20. char *getcwd();
  21.  
  22. #ifndef    FALSE
  23. #define    FALSE    (0)
  24. #endif
  25.  
  26. #ifndef    TRUE
  27. #define    TRUE    !(FALSE)
  28. #endif
  29.  
  30. #define REGFILE    (ST_HIDDEN|ST_SYSTEM|ST_DIRECT)
  31. #define    SET_DTA        0x1a
  32. #define GET_FREE    0x36
  33. #define    FIND_FIRST    0x4e
  34. #define    FIND_NEXT    0x4f
  35.  
  36. struct dirent {
  37.     char rsvd[21];
  38.     char attr;
  39.     short ftime;
  40.     short fdate;
  41.     long fsize;
  42.     char fname[13];
  43. };
  44. #define    NULLENT    (struct dirent *)0
  45.  
  46. #define    insert_ptr(list,new)    (new->next = list,list = new)
  47.  
  48. struct dirsort {
  49.     struct dirsort *next;
  50.     struct dirent de;
  51. };
  52. #define    NULLSORT (struct dirsort *)0
  53.  
  54. /* Create a directory listing in a temp file and return the resulting file
  55.  * descriptor. If full == 1, give a full listing; else return just a list
  56.  * of names.
  57.  */
  58. FILE *
  59. dir(path,full)
  60. char *path;
  61. int full;
  62. {
  63.     FILE *fp;
  64.  
  65.     fp = tmpfile();
  66.     getdir(path,full,fp);
  67.     rewind(fp);
  68.     return fp;
  69. }
  70.  
  71. /* find the first or next file and lowercase it. */
  72. int
  73. nextname(command, name, sbuf)
  74. int command;
  75. char *name;
  76. struct dirent *sbuf;
  77. {
  78.     struct regs regs;
  79.     register char *cp;
  80.     int found;
  81.  
  82.     _AH = SET_DTA;        /* Set disk transfer address */
  83.     _DS = FP_SEG(sbuf);
  84.     _DX = FP_OFF(sbuf);
  85.     sysint(0x21,®s,®s);
  86.  
  87.     _AH = command;        /* Find matching file */
  88.     _CX = REGFILE;
  89.     _DS = FP_SEG(name);
  90.     _DX = FP_OFF(name);
  91.  
  92.     found = (sysint(0x21,®s,®s) & FLAG_CARRY) == 0;
  93.  
  94.     if(found){
  95.         /* strlwr(sbuf->fname); */
  96.         cp = sbuf->fname;
  97.         while ((*cp = tolower(*cp)) != '\0')
  98.             cp++;
  99.     }
  100.  
  101.     return found;
  102. }
  103.  
  104. /* wildcard filename lookup */
  105. filedir(name,times,ret_str)
  106. char *name;
  107. int times;
  108. char *ret_str;
  109. {
  110.     static struct dirent sbuf;
  111.  
  112.     if(!nextname(times == 0 ? FIND_FIRST:FIND_NEXT, name, &sbuf))
  113.         sbuf.fname[0] = '\0';
  114.  
  115.     /* Copy result to output */
  116.     strcpy(ret_str, sbuf.fname);
  117. }
  118. /* do a directory list to the stream 
  119.  * full = 0 -> short form, 1 is long
  120. */
  121. getdir(path,full,file)
  122. char *path;
  123. int full;
  124. FILE *file;
  125. {
  126.     struct dirent sbuf;
  127.     int command = FIND_FIRST;
  128.     int n = 0;
  129.  
  130.     struct dirsort *head, *here, *new;
  131.     void dir_sort(), free_clist();
  132.     void format_fname_full(), print_free_space();
  133.     char *wildcardize();
  134.  
  135.     path = wildcardize(path);
  136.  
  137.     head = NULLSORT;    /* No head of chain yet... */
  138.     for(;;){
  139.         if (!nextname(command, path, &sbuf))
  140.             break;
  141.         command = FIND_NEXT;    /* Got first one already... */
  142.         if (sbuf.fname[0] == '.')    /* drop "." and ".." */
  143.             continue;
  144.  
  145.         new = (struct dirsort *) malloc(sizeof(struct dirsort));
  146.         if(new == NULLSORT){
  147.             /* Clean up and call other routine */
  148.             free_clist(head);
  149.             return getdir_nosort(path,full,file);
  150.         }
  151.         new->de = sbuf;    /* Copy contents of directory entry struct */
  152.  
  153.         /* insert it into the list */
  154.         if (!head || fncmp(new->de.fname, head->de.fname) < 0) {
  155.             insert_ptr(head, new);
  156.         } else {
  157.             register struct dirsort *this;
  158.             for (this = head;
  159.                 this->next != NULLSORT;
  160.                 this = this->next)
  161.                 if (fncmp(new->de.fname, this->next->de.fname) < 0)
  162.                     break;
  163.             insert_ptr(this->next, new);
  164.         }
  165.     } /* infinite FOR loop */
  166.  
  167.     for (here = head; here; here = here->next)
  168.         format_fname_full(file,&here->de,full,++n);
  169.  
  170.     /* Give back all the memory we temporarily needed... */
  171.     free_clist(head);
  172.  
  173.     if(full) print_free_space(file, n);
  174.  
  175.     return 0;
  176. }
  177. int
  178. fncmp(a,b)
  179. register char *a, *b;
  180. {
  181.         int i;
  182.  
  183.     for(;;){
  184.         if (*a == '.') return -1;
  185.         if (*b == '.') return 1;
  186.         if ((i = *a - *b++) != 0) return i;
  187.         if (!*a++) return -1;
  188.     }
  189. }
  190. /* Change working directory */
  191. docd(argc,argv)
  192. int argc;
  193. char *argv[];
  194. {
  195.     char dirname[128];
  196.  
  197.     if(argc > 1){
  198.         if(chdir(argv[1]) == -1){
  199.             printf("Can't change directory\n");
  200.             return 1;
  201.         }
  202.     }
  203.     if(getcwd(dirname,128) != NULLCHAR){
  204.         printf("\\%s\n",dirname);
  205.     }
  206.     return 0;
  207. }
  208. /* List directory to console */
  209. dodir(argc,argv)
  210. int argc;
  211. char *argv[];
  212. {
  213.     char *path;
  214.  
  215.     if(argc >= 2){
  216.         path = argv[1];
  217.     } else {
  218.         path = "*.*";
  219.     }
  220.     getdir(path,1,stdout);
  221.     return 0;
  222. }
  223.  
  224.  
  225. /*
  226.  * Return a string with commas every 3 positions.
  227.  * If malloc() fails, return original string unmodified.
  228.  * else the original string is replace with the string with commas.
  229.  *
  230.  * The caller must be sure that there is enough room for the resultant
  231.  * string.
  232.  *
  233.  *
  234.  * k3mc 4 Dec 87
  235.  */
  236. void
  237. commas(dest)
  238. char *dest;
  239. {
  240.     char *src, *core;    /* Place holder for malloc */
  241.     unsigned cc;        /* The comma counter */
  242.     unsigned len;
  243.  
  244.     len = strlen(dest);
  245.     /* Make a copy, so we can muck around */
  246.     if( (core = src = strdup(dest)) == NULLCHAR)
  247.         return;
  248.  
  249.     cc = (len-1)%3 + 1;    /* Tells us when to insert a comma */
  250.  
  251.     while(*src != '\0'){
  252.         *dest++ = *src++;
  253.         if( ((--cc) == 0) && *src ){
  254.             *dest++ = ','; cc = 3;
  255.         }
  256.     }
  257.     free(core);
  258.     *dest = '\0';
  259. }
  260. /* fix up the filename so that it contains the proper wildcard set */
  261. char *
  262. wildcardize(path)
  263. char *path;
  264. {
  265.     struct dirent sbuf;
  266.     static char ourpath[64];
  267.  
  268.     /* Root directory is a special case */
  269.     if(path == NULLCHAR ||
  270.        *path == '\0' ||
  271.        strcmp(path,"\\") == 0 ||
  272.        strcmp(path,"/") == 0)
  273.         path = "\\*.*";
  274.  
  275.     /* if they gave the name of a subdirectory, append \*.* to it */
  276.     if (nextname(FIND_FIRST, path, &sbuf) &&
  277.         (sbuf.attr & ST_DIRECT) &&
  278.         !nextname(FIND_NEXT, path, &sbuf)) {
  279.  
  280.         /* if there isn't enough room, give up -- it's invalid anyway */
  281.         if (strlen(path) + 4 > 63) return path;
  282.         strcpy(ourpath, path);
  283.         strcat(ourpath, "\\*.*");
  284.         return ourpath;
  285.     }
  286.     return path;
  287. }
  288.  
  289. void
  290. format_fname_full(file, sbuf, full, n)
  291. FILE *file;
  292. struct dirent *sbuf;
  293. int full, n;
  294. {
  295.     char line_buf[50];        /* for long dirlist */
  296.     char cbuf[20];            /* for making line_buf */
  297.  
  298.     strcpy(cbuf,sbuf->fname);
  299.     if(sbuf->attr & ST_DIRECT) strcat(cbuf, "\\");
  300.     if (full) {
  301.         /* Long form, give other info too */
  302.         sprintf(line_buf,"%-13s",cbuf);
  303.         if(sbuf->attr & ST_DIRECT)
  304.             strcat(line_buf,"           ");/* 11 spaces */
  305.         else {
  306.             sprintf(cbuf,"%ld",sbuf->fsize);
  307.             commas(cbuf);
  308.             sprintf(line_buf+strlen(line_buf),"%10s ",cbuf);
  309.         }
  310.         sprintf(line_buf+strlen(line_buf),"%2d:%02d %2d/%02d/%02d%s",
  311.           (sbuf->ftime >> 11) & 0x1f,    /* hour */
  312.           (sbuf->ftime >> 5) & 0x3f,    /* minute */
  313.           (sbuf->fdate >> 5) & 0xf,    /* month */
  314.           (sbuf->fdate ) & 0x1f,        /* day */
  315.           (sbuf->fdate >> 9) + 80,    /* year */
  316.           (n & 1) ? "   " : "\n");
  317.         fputs(line_buf,file);
  318.     } else {
  319.         fputs(cbuf,file);
  320.         fputs("\n",file);
  321.     }
  322. }
  323. /* Provide additional information only on DIR */
  324. void
  325. print_free_space(file, n)
  326. FILE *file;
  327. int n;
  328. {
  329.     unsigned long free_bytes, total_bytes;
  330.     char s_free[11], s_total[11];
  331.     char cbuf[20];
  332.     struct regs regs;
  333.  
  334.     if(n & 1)
  335.         fputs("\r\n",file);
  336.  
  337.     /* Find disk free space */
  338.     _AH = GET_FREE;
  339.     _DX = 0;        /* Default drive */
  340.     if(sysint(0x21,®s,®s) & FLAG_CARRY)
  341.         ;
  342.  
  343.     free_bytes  = (unsigned long)_AX * (unsigned long)_CX;
  344.     total_bytes = free_bytes * (unsigned long)_DX;
  345.     free_bytes *= (unsigned long)_BX;
  346.  
  347.     sprintf(s_free,"%ld",free_bytes);    commas(s_free);
  348.     sprintf(s_total,"%ld",total_bytes);    commas(s_total);
  349.  
  350.     if(n)
  351.         sprintf(cbuf,"%d",n);
  352.     else
  353.         strcpy(cbuf,"No");
  354.  
  355.     fprintf(file,"%s file%s. %s bytes free. Disk size %s bytes.\n",
  356.         cbuf,(n==1? "":"s"),s_free,s_total);
  357. }
  358. void
  359. free_clist(this)
  360. struct dirsort *this;
  361. {
  362.     struct dirsort *next;
  363.  
  364.     while (this != NULLSORT) {
  365.         next = this->next;
  366.         free(this);
  367.         this = next;
  368.     }
  369. }
  370. getdir_nosort(path,full,file)
  371. char *path;
  372. int full;
  373. FILE *file;
  374. {
  375.     struct dirent sbuf;
  376.     int command;
  377.     int n = 0;    /* Number of directory entries */
  378.     void format_fname_full(), print_free_space();
  379.  
  380.     path = wildcardize(path);
  381.     command = FIND_FIRST;
  382.     while(nextname(command, path, &sbuf)){
  383.         command = FIND_NEXT;    /* Got first one already... */
  384.         if (sbuf.fname[0] == '.')    /* drop "." and ".." */
  385.             continue;
  386.         format_fname_full(file, &sbuf, full, ++n);
  387.     }
  388.     if(full)
  389.         print_free_space(file, n);
  390.     return 0;
  391. }
  392.  
  393.  
  394.